package com.acwing.partition12;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author `RKC`
 * @date 2022/1/16 9:59
 */
public class AC1125牛的旅行 {

    private static final int N = 155;
    private static final double INF = 1e20;

    private static char[][] matrix = new char[N][N];
    private static double[][] dist = new double[N][N];

    private static List<int[]> points = new ArrayList<>(N);

    private static double[] maxDist = new double[N];
    private static int n = 0;

    private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    private static final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

    public static void main(String[] args) throws IOException {
        n = Integer.parseInt(reader.readLine());
        //读入点的坐标
        for (int i = 0; i < n; i++) {
            String[] s = reader.readLine().split("\\s+");
            points.add(new int[]{Integer.parseInt(s[0]), Integer.parseInt(s[1])});
        }
        //读入连通性矩阵
        for (int i = 0; i < n; i++) {
            String s = reader.readLine();
            for (int j = 0; j < n; j++) matrix[i][j] = s.charAt(j);
        }
        writer.write(String.format("%.6f\n", floyd()));
        writer.flush();
    }

    private static double floyd() {
        //根据点和连通性矩阵初始化dist矩阵
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == j) continue;
                //如果属于同一个连通块才进行计算，不属于同一个连通块就表示不连通
                dist[i][j] = matrix[i][j] == '1' ? calDist(points.get(i), points.get(j)) : INF;
            }
        }
        //floyd算法，计算出一个连通块内任意两点之间的距离
        for (int k = 0; k < n; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }
        //合并后的直径有可能来自于两种情况 1：直径是两个连通块最大的一个（其中一个连通块并入了另一个连通块） 2：两个连通块不存在包含关系
        double ans1 = 0, ans2 = INF;
        //处理每个点在自己连通区域内的最远的距离
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (dist[i][j] < INF) {
                    maxDist[i] = Math.max(maxDist[i], dist[i][j]);
                    ans1 = Math.max(ans1, maxDist[i]);
                }
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (dist[i][j] >= INF) {
                    //两个点不在同一个连通块，计算两点的距离
                    double dis = calDist(points.get(i), points.get(j));
                    ans2 = Math.min(ans2, maxDist[i] + maxDist[j] + dis);
                }
            }
        }
        return Math.max(ans1, ans2);
    }

    private static double calDist(int[] p1, int[] p2) {
        return Math.sqrt(Math.pow(p1[0] - p2[0], 2) + Math.pow(p1[1] - p2[1], 2));
    }
}
